home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / ab20 / hardware / amscsi.lzh / scsidrvr.asm < prev    next >
Assembly Source File  |  1987-05-26  |  9KB  |  307 lines

  1. ;---------------------------------------------------------------;
  2. ;---------------------------------------------------------------;
  3. ;       SCSI DRIVER - for AMSCSI hardware            ;
  4. ;       NCR 53C80 - SCSI ctrl chip                ;
  5. ;    Rich Frantz        24-may-87            ;    
  6. ;        Version 0.1                    ;
  7. ;    This routine should be called from a DOS handler    ;
  8. ;    it should be noted that all command data should be    ;
  9. ;    checked for validity before calling. Also I have     ;
  10. ;    not finished the error handling.            ;
  11. ;---------------------------------------------------------------;
  12. ;---------------------------------------------------------------;
  13.  
  14. ; equates
  15.  
  16. NCR    equ    $800001        ;SCSI ctrl chip            
  17. M250    equ    $1E000        ;250 mSEC dly            
  18. U200    equ    $64        ;200 uSEC dly
  19. SELlp    equ    $100        ;Selection timeout
  20. LUv    equ    $1        ;select drive 0
  21. TarIDv    equ    $1        ;target I D 
  22. InitIDv    equ    $8        ;Initiator I D
  23. ;
  24. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  25. ;            REMOVE THIS START UP ROUTINE WHEN USING 
  26. ;    AS A REAL AMIGA DRIVER - THE CALLING ROUTINE SHOULD
  27. ;    CALL ReadSCSI: , WriteSCSI: , or FormatSCSI: DIRECTLY
  28. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  29. ;            equates for test routines ( START )
  30. ;
  31. Data_Len    equ    $100
  32. Sect        equ    $140000    ;bytes not sectors        
  33. Loop        equ    100
  34. Data_Len1    equ    $300
  35. Sect1        equ    $200
  36.  
  37. ;---------------------------------------------------------------;
  38. ;    a0 = IO_DATA - MUST BE SETUP BY CALLER            ;
  39. ;    a6 = DEVICE POINTER - MUST BE SETUP BY CALLER        ;
  40. ;       a4 = SCSI buffer pointer                ;
  41. ;       a5 = unassigned                     ;
  42. ;     d0 = IO_LENGTH ( in bytes) - MUST BE SETUP BY CALLER    ;
  43. ;       d1 = IO_OFFSET - MUST BE SETUP BY CALLER        ;
  44. ;    d4 = unassigned - used by driver            ;
  45. ;       d5 = unassigned - used by driver            ;
  46. ;    d6 = Tid - setup by this driver    (target I D)        ;
  47. ;    d7 = Iid - setup by this driver (iniator I D)        ;
  48. ;---------------------------------------------------------------;
  49.  
  50. START:    ; this starts the program by fake setting the regs
  51.     move.l #Loop,d2        ;set loop counter
  52.     move.b #TarIDv,TarID    ;set up traget ID
  53.     move.b #InitIDv,InitID    ;set up initiator ID
  54.     move.b #LUv,LU        ;set up logical unit #
  55. STLP:    move.l #Data_Buf,a0    ;set up IO_DATA
  56.     move.l #Data_Len,d0    ;set up IO_LENGTH
  57.     move.l #Sect,d1        ;set up IO_OFFSET
  58.     bsr WriteSCSI        ;go write it
  59.     move.l #Data_Len1,d0    ;get new IO_LENGTH
  60.     move.l #Sect1,d1    ;get new IO_OFFSET
  61.     bsr ReadSCSI        ;go read it
  62.     subq.l #1,d2        ;dec counter
  63.     bne.s STLP
  64.     rts            ;done
  65. ReadSCSI:    ;read data from the SCSI 
  66.     movem.l d4/d5/d6/d7/a4/a5,-(sp)    ;save regs
  67.     bsr Build_CMD            ;build the scsi cmd packet
  68.     btst.b #0,ERROR            ;check for any error
  69.     bne.s ReadSCSI_End        ;if so, exit
  70.     move.b #$08,CMDBUF        ;set cmd to read
  71.     bsr SELph            ;select the target
  72.  
  73. ReadSCSI_End:    
  74.     movem.l (sp)+,d4/d5/d6/d7/a4/a5    ;restore regs
  75.     rts                ;return to caller
  76.  
  77. WriteSCSI:    ;send data to the SCSI
  78.     movem.l d4/d5/d6/d7/a4/a5,-(sp)    ;save regs
  79.     bsr Build_CMD            ;build the scsi cmd packet
  80.     btst.b #0,ERROR            ;check for any error
  81.     bne.s WriteSCSI_End        ;if so, exit
  82.     move.b #$0A,CMDBUF        ;set cmd to write
  83.     bsr SELph            ;do it
  84.  
  85. WriteSCSI_End:
  86.     movem.l (sp)+,d4/d5/d6/d7/a4/a5    ;restoer regs
  87.     rts                ;return to caller
  88.  
  89. FormatSCSI:
  90.     movem.l d4/d5/d6/d7/a4/a5,-(sp)    ;save the regs
  91.     move.w #$0400,CMDBUF        ;set the cmd
  92.     move.l #0,CMDBUF+2        ;clr the cmd packet
  93.     bsr Unit_No            ;set I D's & L U #
  94.     btst.b #0,ERROR            ;check for any error
  95.     bne.s FormatSCSI_End        ;if so, end
  96.     bsr SELph            ;do it
  97.  
  98. FormatSCSI_End:
  99.     movem.l (sp)+,d4/d5/d6/d7/a4/a5    ;restore th regs
  100.     rts                ; return to caller
  101.  
  102. Request_Sense:
  103.     movem.l d4/d5/d6/d7/a4/a5,-(sp)    ;save regs
  104.     move.w #$0300,CMDBUF        ;set the cmd
  105.     move.l #0,CMDBUF+2        ;clr the rest of the packet
  106.     bsr Unit_No            set I D's & L U #
  107.     btst.b #0,ERROR            ;check for any error
  108.     bne.s Request_End        ;if so exit
  109.     bsr SELph            ;do it
  110.  
  111. Request_End:
  112.     movem.l (sp)+,d4/d5/d6/d7/a4/a5    ;restore regs
  113.     rts
  114. Build_CMD:    ;build the scsi cmd packet
  115.     move.l d1,d4            ;get the start sect #
  116.     move.l d0,d5            ;get the #bytes to transfere
  117.     asr.l #8,d5            ;shift 8 palces to get sectors
  118.     and.l #$FF,d5            ;must be less than 1 byte
  119.     asl.l #8,d5            ;move to upper byte in word
  120.     move.w d5,CMDBUF+4        ;place in packet
  121.     asr.l #8,d4            ;convert to sectors
  122.     and.l #$000FFFFF,d4        ;mask out L U #
  123.     move.l d4,CMDBUF        ;place in packet
  124. Unit_No:    ; add the logical unit # & get I D's
  125.     move.l #$01,d5            ;load d0
  126.     move.l #$0,d4            ;clear d4
  127.     move.b TarID,d4            ;get TarID
  128.     subq.l #$01,d4            ;-1
  129.     bmi ID_ERROR            ;oops ! TARGET ID NO GOOD
  130.     asl.l d4,d5            ;shift TarID palces
  131.     move.b d5,d6            ;store in target I D
  132.     move.l #$01,d5            ;same for the Initiator (us)
  133.     move.l #$0,d4            ;clear d4
  134.     move.b InitID,d4        ;get InitID 
  135.     subq.l #$01,d4            ;-1
  136.     bmi ID_ERROR            ;oops ! INIT ID NO GOOD
  137.     asl.l d4,d5            
  138.     move.b d5,d7            ;store in Init I D
  139. ;    get Logical Unit # (drive #)
  140.     move.l #$0,d5            ;clear d5
  141.     move.b LU,d5            ;get the drive number
  142.     asl.l #$5,d5            ;shift to LUN
  143.     and.l #$E0,d5            ;mask all other bits
  144.     or.b d5,CMDBUF+1        ;put it in the packet
  145.     rts                ;packet complete    
  146.  
  147. ID_ERROR:
  148.     move.b #$01,ERROR        ;set the drive not ready error
  149.     rts    
  150.     
  151. SELph:        ;select the target
  152.     move.l #SELlp,d4    ;set SEL loop value
  153. SELph1:    move.b #0,NCR+2        ;clr NCR
  154.     move.b #0,NCR+4
  155.     move.b #0,NCR+8
  156. ARB:    move.b d7,NCR        ;ld init I D
  157.     or.b #1,NCR+4        ;set ARB bit
  158. NFREE:    subq.l #$01,d4        ;dec SEL loop
  159.     beq SEL_ERROR        ;stuck in the loop
  160.     btst.b #6,NCR+2        ;check arib in proc.
  161.     beq NFREE        ;wait
  162.     nop            ;delay for bus settle
  163.     nop
  164.     nop
  165.     nop
  166.     btst.b #5,NCR+2        ;check lost arb
  167.     bne.s SELph1        ;try again
  168. ;
  169. ;check for higher priority
  170. ;
  171.     move.l #0,d5        ;lcr d5
  172.     move.b NCR,d5        ;load scsi data
  173.     sub.b d7,d5        ;sub our id
  174.     beq.s WIN        ;if = we are the only bidder
  175.     sub.b d7,d5        ;sub again
  176.     bmi.s WIN        ;if - we are the highest
  177.     bra.s SELph1        ;try again
  178. WIN:    btst.b #5,NCR+2        ;check lost arb bit
  179.     bne.s SELph1        ;if lost , retry
  180.     move.b #$0c,NCR+2    ;set SEL
  181.     nop            ;delay
  182.     nop
  183.     nop
  184.     nop
  185.     move.b d7,NCR        ;load init I D
  186.     or.b d6,NCR        ;load target I D
  187.     move.b #5,NCR+2        ;set SEL & Data Bus
  188.     and.b #$FE,NCR+4    ;clr ARB
  189.     and.b #$F7,NCR+2    ;clr BSY
  190.     move.l #M250,d5        ;load timer
  191. loop1:    btst.b #6,NCR+8        ;test BSY
  192.     bne.s SLECT        ;if busy , selected
  193.     subq #1,d5        ;dec timer
  194.     bne.s loop1        ;loop
  195.     move.b #0,NCR        ;clr I D's
  196.     move.l #U200,d5        ;load timer
  197. loop2:    btst.b #6,NCR        ;test BSY
  198.     bne.s SLECT        ;if busy , selected
  199.     subq #1,d5        ;dec timer
  200.     bne.s loop2        ;loop
  201.     bra SEL_ERROR        ;selection failed
  202. SLECT:    and.b #$FB,NCR+2    ;clr SEL
  203. ; NextPhase
  204. NextPhase:    ;Check the SCSI bus phase
  205.     btst.b #7,NCR+8        ;check RESET
  206.     bne RSTph        ;reset phase
  207.     btst.b #6,NCR+8        ;check BUSY
  208.     beq Done        ;bus free
  209.     btst.b #3,NCR+8        ;check C/D
  210.     beq.s Dat        ;data in/out phase
  211.     btst.b #4,NCR+8        ;check MSG
  212.     bne.s Message        ;Message in/out phase
  213.     btst.b #2,NCR+8        ;check I/O
  214.     bne.s STATph        ;stat phase
  215.     bra.s CMDph        ;command phase
  216. Message:    ;check to see if it is message in or out
  217.     btst.b #2,NCR+8        ;check I/O
  218.     bne.s MSGINph        
  219.     bra.s MSGOUTph
  220. Dat:        ;check to see if it is data in or out
  221.     btst.b #2,NCR+8        ;check I/O
  222.     bne.s RDATph
  223.     bra.s SDATph    
  224. Done:        ;did we end normally ?
  225.     btst.b #1,STAT        ;do we have an error
  226.     bne Return_ERROR
  227.      rts            ;return to caller
  228.  
  229. RSTph:        ;reset phase
  230.     bra.s Done        ;done
  231. CMDph:        ;send command
  232.     move.l #CMDBUF,a4    ;set the cmd buffer add
  233.     move.b #$02,NCR+6    ;set TCR to command phase
  234.     bra.s Send        ;send the command
  235.  
  236. STATph:        ;get status byte
  237.     move.l #STAT,a4        ;set the stat buffer add
  238.     move.b #$03,NCR+6    ;set TCR to status phase
  239.     bra.s Rec        ;get the stat
  240.  
  241. MSGINph:     ;get message from target
  242.     move.l #MSGINBUF,a4    ;set the message in buffer add
  243.     move.b #$07,NCR+6    ;set TCR to message in phase
  244.     bra.s Rec        ;get the message
  245.  
  246. MSGOUTph:    ;send message to target
  247.     bra NextPhase        ;error try again
  248.  
  249. RDATph:        ;receive data fron target
  250.     move.l a0,a4        ;set the data buffer add
  251.     move.b #$01,NCR+6     ;set TCR to receive data
  252.     bra.s Rec        ;get the data
  253.  
  254. SDATph:        ;send data to target
  255.     move.l a0,a4        ;set the data buffer add
  256.     move.b #$00,NCR+6    ;set TCR to send data
  257.     
  258. Send:        ;send x characters to the target
  259.     move.b (a4)+,NCR    ;set the byte
  260. Send1:    btst.b #5,NCR+8        ;test for REQ
  261.     beq.s Send1        ;wait for REQ
  262.     or.b #$10,NCR+2        ;set ACK
  263. Send2:    btst.b #5,NCR+8        ;test REQ
  264.     bne.s Send2        ;wait for /REQ
  265.     andi.b #$EF,NCR+2    ;clr ACK
  266.     btst.b #3,NCR+10    ;test pahse match
  267.     bne.s Send    
  268.     bra NextPhase
  269.  
  270. Rec:        ;receive x characters form the target
  271. Rec1:    btst.b #5,NCR+8        ;test REQ
  272.     beq.s Rec1        ;wait for REQ
  273.     move.b NCR,(a4)+    ;get byte from target
  274.     or.b #$10,NCR+2        ;set ACK
  275. Rec2:    btst.b #5,NCR+10    ;test REQ
  276.     bne.s Rec2        ;wait for /REQ
  277.     andi.b #$EF,NCR+2
  278.     btst.b #3,NCR+10    ;test for phase match
  279.     bne.s Rec    
  280.     bra NextPhase
  281.  
  282. SEL_ERROR:
  283.     move.b #$01,ERROR    ;set drive not ready error
  284.     rts
  285.  
  286. Return_ERROR:
  287.     ;must be finnished
  288.     rts            ;return to caller
  289.  
  290. CMDBUF    dc.b $0A,$00,$00,$00,$01,$00    ;command string (write 1 block)
  291.  
  292. STAT        ds.b $01    ;status word
  293.  
  294. MSGINBUF    ds.b $04    ;message buffer
  295.  
  296. TarID        ds.b $01    ;target ID location
  297.  
  298. InitID        ds.b $01    ;initiator ID location
  299.  
  300. ERROR        ds.b $01    ;error flag
  301.  
  302. LU        ds.b $01    ;logical unit #
  303.  
  304. Data_Buf    ds.b $500    ;data buffer (reduce the size when real)
  305.  
  306.     end
  307.